const http = require("http");
const slice = Array.prototype.slice;

class LikeExpress {
  constructor() {
    // 存放中间件的列表
    this.routes = {
      all: [], // app.use(...)
      get: [], // app.get(...)
      post: [], // app.post(...)
    };
  }
  register(path) {
    const info = {};
    if (typeof path === "string") {
      info.path = path;
      info.stack = slice.call(arguments, 1);
    } else {
      info.path = "/";
      info.stack = slice.call(arguments, 0);
    }
    return info;
  }
  use() {
    const info = this.register.apply(this, arguments);
    this.routes.all.push(info);
  }
  get() {
    const info = this.register.apply(this, arguments);
    this.routes.get.push(info);
  }
  post() {
    const info = this.register.apply(this, arguments);
    this.routes.post.push(info);
  }
  // 匹配当前路由对应的中间件
  match(method, url) {
    let stack = [];
    if (url === "/favicon.ico") return stack; // 过滤请求 favicon.ico
    // 获取 routes 中对应的请求方法
    const curRoutes = [].concat(this.routes.all).concat(this.routes[method]);
    console.log("curRoutes", curRoutes);
    curRoutes.forEach((routeInfo) => {
      // 根，父，完全相等三种情况
      if (url.indexOf(routeInfo.path) === 0) {
        // url === '/api/get-cookie' 且 routeInfo.path === '/'
        // url === '/api/get-cookie' 且 routeInfo.path === '/api'
        // url === '/api/get-cookie' 且 routeInfo.path === '/api/get-cookie'
        stack = stack.concat(routeInfo.stack);
      }
    });
    console.log("stack", stack);
    return stack;
  }
  // 核心的 next 机制
  handle(req, res, stack) {
    const next = () => {
      const middleware = stack.shift(); // 第一个中间件
      if (middleware) middleware(req, res, next); // 执行中间件函数
      else res.json("Cannot GET /api 404");
    };
    next(); // 开始执行第一个中间件
  }
  // createServer 回调函数
  callback() {
    return (req, res) => {
      // 封装 json
      res.json = (data) => {
        res.setHeader("Content-type", "application/json");
        res.end(JSON.stringify(data));
      };
      const url = req.url; // 方法
      const method = req.method.toLowerCase(); // 小写化
      const resultList = this.match(method, url); // 匹配中间件
      this.handle(req, res, resultList);
    };
  }

  listen(...args) {
    const server = http.createServer(this.callback());
    server.listen(...args);
  }
}

// 工厂函数
module.exports = () => {
  return new LikeExpress();
};
